using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Claims;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using backend.Models;
using backend.Models.Dtos;
using backend.Repositories;
using backend.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Services;

namespace backend.Controllers
{
    [EnableCors]
    [ApiController]
    [Route("api/users")]
    public class UsersController : ControllerBase
    {
        private readonly UserRepo _userRepo;
        private readonly MaintenanceManRepo _maintenanceManRepo;

        public UsersController(UserRepo userRepo, MaintenanceManRepo maintenanceManRepo)
        {
            _userRepo = userRepo;
            _maintenanceManRepo = maintenanceManRepo;
        }

        [HttpGet]
        public async Task<IActionResult> GetUsers([FromQuery] string role, int page = 1, int number = 10)
        {
            try
            {
                var principal = JwtHelper.GetAndValidateJwtToken(Request);
                if (principal == null)
                {
                    return StatusCode(401, new { code = "failure", description = "Unauthorized" });
                }
                if (principal.Role != "2")
                {
                    return StatusCode(403, new { code = "failure", description = "Forbidden" });
                }
                if (role == "1")
                {
                    var users = await _maintenanceManRepo.GetMaintenanceMenList(role, page, number);
                    var totalCount = await _maintenanceManRepo.GetTotalMMCountAsync();

                    var response = new
                    {
                        code = "success",
                        data = users,
                        total = totalCount,
                        page = page,
                        number = number
                    };

                    return Ok(response);
                } else if (role == "0")
                {
                    var users = await _userRepo.GetUserList(role, page, number);
                    var totalCount = await _userRepo.GetTotalUsersCountAsync(role);

                    var response = new
                    {
                        code = "success",
                        data = users,
                        total = totalCount,
                        page = page,
                        number = number
                    };

                    return Ok(response);
                }
                return StatusCode(400, new { code = "failure", description = "Invalid role" });
                
            }
            catch (Exception ex)
            {
                return StatusCode(400, new { code = "failure", description = ex.Message });
            }
        }

        [HttpGet("{userID}")]
        public async Task<IActionResult> GetMaintenanceMan(string userID)
        {
            try
            {
                var principal = JwtHelper.GetAndValidateJwtToken(Request);
                if (principal == null)
                {
                    return StatusCode(401, new { code = "failure", description = "Unauthorized" });
                }
                if (principal.Role != "2")
                {
                    return StatusCode(403, new { code = "failure", description = "Forbidden" });
                }
                var maintenanceMan = await _maintenanceManRepo.GetMaintenanceManByIdAsync(userID);

                if (maintenanceMan == null)
                {
                    return StatusCode(200, new { code = "failure", description = "User not found" });
                }
                var response = new
                {
                    code = "success",
                    data = maintenanceMan
                };

                return Ok(response);
            }
            catch (Exception ex)
            {
                return StatusCode(400, new { code = "failure", description = ex.Message });
            }
        }

        // only admin can update mm
        [HttpPatch("{mid}")]
        public async Task<IActionResult> UpdateMaintenanceManAsync(string mid, MaintenanceManAllUpdateDto maintenanceManAllUpdateDto)
        {
            var principal = JwtHelper.GetAndValidateJwtToken(Request);
            if (principal == null)
            {
                return StatusCode(401, new { code = "failure", description = "Unauthorized" });
            }
            if (principal.Role != "2")
            {
                return StatusCode(403, new { code = "failure", description = "Forbidden" });
            }
            if (maintenanceManAllUpdateDto == null)
            {
                return BadRequest("Maintenance man all update DTO cannot be null.");
            }

            try
            {
                var userUpdateDto = new UserUpdateDto
                {
                    UName = maintenanceManAllUpdateDto.UName,
                    UContact = maintenanceManAllUpdateDto.UContact
                };

                var maintenanceManUpdateDto = new MaintenanceManUpdateDto
                {
                    PId = maintenanceManAllUpdateDto.PId,
                    MHiredate = maintenanceManAllUpdateDto.MHiredate,
                    MIsResigned = maintenanceManAllUpdateDto.MIsResigned
                };

                // 更新User
                var userUpdated = await _userRepo.UpdateUserAsync(mid, userUpdateDto);
                if (!userUpdated)
                {
                    return NotFound($"User with ID '{mid}' not found.");
                }

                // 更新MaintenanceMan
                var maintenanceManUpdated = await _maintenanceManRepo.UpdateMaintenanceManAsync(mid, maintenanceManUpdateDto);
                if (!maintenanceManUpdated)
                {
                    return NotFound($"Maintenance man with ID '{mid}' not found.");
                }

                return Ok(new { code = "success", message = "Maintenance man and user updated successfully." });
            } catch (Exception ex)
            {
                return StatusCode(400, new { code = "failure", description = ex.Message });
            }

        }

        [HttpPost]
        public async Task<IActionResult> Register([FromBody] UserRegisterDto user)
        {
            try
            {
                // validate userID format
                if (!IsValidUserId(user.UId))
                {
                    return StatusCode(200, new { code = "failure", description = "Invalid UserId." });
                }

                if (!IsValidPhoneNumber(user.UContact))
                {
                    return StatusCode(200, new { code = "failure", description = "Invalid phone number." });
                }

                if (await _userRepo.GetUserByIdAsync(user.UId) != null)
                {
                    return StatusCode(200, new { code = "failure", description = "User already exists." });
                }

                // validate password format
                if (!IsValidPassword(user.UPassword))
                {
                    return StatusCode(200, new { code = "failure", description = "Invalid password. Password must be at least 8 characters long and contain at least one uppercase letter, one lowercase letter, and one digit." });
                }

                if (user.URole != "0" && user.URole != "1")
                {
                    return StatusCode(200, new { code = "failure", description = "Invalid role. Role must be 0 or 1." });
                }
                user.UPassword = PasswordHasher.HashPassword(user.UPassword);
                var maintenanceManDto = new MaintenanceManCreateDto { MId = user.UId, PId = "0" };
                await _maintenanceManRepo.AddMaintenanceManAsync(maintenanceManDto);
                await _userRepo.AddUserAsync(user);
                await _maintenanceManRepo.SaveChangesAsync();
                await _userRepo.SaveChangesAsync();
                return StatusCode(200, new { code = "success" });
            }
            catch (Exception ex)
            {
                return StatusCode(400, new { code = "failure", description = ex.Message });
            }
        }

        [HttpPost("login")]
        [AllowAnonymous]
        public async Task<IActionResult> Login([FromBody] UserLoginDto loginModel)
        {
            var user = await _userRepo.GetUserByIdAsync(loginModel.UId);
            Console.WriteLine(user?.UPassword);
            Console.WriteLine(loginModel.UPassword);
            if (user == null || !PasswordHasher.VerifyPassword(loginModel.UPassword, user.UPassword))
            {
                return StatusCode(200, new { code = "failure", description = "Invalid credentials" });
            }

            var token = JwtHelper.GenerateJwtToken(user.UId, user.URole);

            return StatusCode(200, new { code = "success", data = token });
        }

        // [HttpGet]
        // [Authorize(Roles = "2")] // Only Admin can get the list of users
        // public async Task<IActionResult> GetUsers([FromQuery]int role, int page = 1, int number = 10)
        // {
        //     var users = await _userRepo.GetUsersByRoleAsync(role, page, number);
        //     return Ok(new { code = "success", data = users });
        // }

        // only admin can delete user
        [HttpDelete("{userID}")]
        public async Task<IActionResult> DeleteUser(string userID)
        {
            try
            {
                var principal = JwtHelper.GetAndValidateJwtToken(Request);
                if (principal == null)
                {
                    return StatusCode(401, new { code = "failure", description = "Unauthorized" });
                }
                if (principal.Role != "2")
                {
                    return StatusCode(403, new { code = "failure", description = "Forbidden" });
                }
                
                var success = await _userRepo.RemoveUserAsync(userID);
                if (!success)
                {
                    return StatusCode(400, new { code = "failure", description = "User could not be removed or is protected" });
                }
                return Ok(new { code = "success" });
            }
            catch (Exception ex)
            {
                return StatusCode(400, new { code = "failure", description = ex.Message });
            }
        }

        private bool IsValidUserId(string userId)
        {
            // 假设主流平台的UserId规则如下：4到12个字符，包含字母、数字和下划线
            const string pattern = @"^[a-zA-Z0-9_]{4,12}$";
            return Regex.IsMatch(userId, pattern) && !Regex.IsMatch(userId, @"\s");
        }

        private bool IsValidPassword(string password)
        {
            // 密码必须至少8位长，并且包含至少一个大写字母、一个小写字母和一个数字
            const string pattern = @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$";
            return Regex.IsMatch(password, pattern) && !Regex.IsMatch(password, @"\s"); ;
        }

        private bool IsValidPhoneNumber(string phoneNumber)
        {
            // 手机号码格式验证
            const string pattern = @"^1[3-9]\d{9}$";
            return Regex.IsMatch(phoneNumber, pattern);
        }
    }
}